package org.example.trigger.http;

import lombok.extern.slf4j.Slf4j;
import org.example.api.response.Response;
import org.springframework.http.HttpStatus;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseStatus;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import org.springframework.web.bind.support.WebExchangeBindException;
import org.springframework.web.server.ResponseStatusException;
import org.springframework.web.server.ServerWebInputException;
import reactor.core.publisher.Mono;

/**
 * 全局异常处理器
 */
@Slf4j
@RestControllerAdvice
public class GlobalExceptionHandler {

    /**
     * 处理参数验证异常
     */
    @ExceptionHandler(WebExchangeBindException.class)
    @ResponseStatus(HttpStatus.BAD_REQUEST)
    public Mono<Response<Void>> handleValidationException(WebExchangeBindException ex) {
        String message = ex.getBindingResult().getFieldErrors().stream()
                .map(error -> error.getField() + ": " + error.getDefaultMessage())
                .reduce((a, b) -> a + ", " + b)
                .orElse("参数验证失败");

        log.warn("Validation exception: {}", message);

        return Mono.just(Response.<Void>builder()
                .code("400")
                .info(message)
                .build());
    }

    /**
     * 处理请求参数异常
     */
    @ExceptionHandler(ServerWebInputException.class)
    @ResponseStatus(HttpStatus.BAD_REQUEST)
    public Mono<Response<Void>> handleInputException(ServerWebInputException ex) {
        log.warn("Input exception: {}", ex.getMessage());

        return Mono.just(Response.<Void>builder()
                .code("400")
                .info("请求参数错误: " + ex.getReason())
                .build());
    }

    /**
     * 处理HTTP状态异常
     */
    @ExceptionHandler(ResponseStatusException.class)
    public Mono<Response<Void>> handleResponseStatusException(ResponseStatusException ex) {
        log.warn("Response status exception: {}", ex.getMessage());

        return Mono.just(Response.<Void>builder()
                .code(String.valueOf(ex.getStatusCode().value()))
                .info(ex.getReason())
                .build());
    }

    /**
     * 处理运行时异常
     */
    @ExceptionHandler(RuntimeException.class)
    @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
    public Mono<Response<Void>> handleRuntimeException(RuntimeException ex) {
        log.error("Runtime exception", ex);

        return Mono.just(Response.<Void>builder()
                .code("500")
                .info("系统内部错误")
                .build());
    }

    /**
     * 处理其他异常
     */
    @ExceptionHandler(Exception.class)
    @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
    public Mono<Response<Void>> handleException(Exception ex) {
        log.error("Unexpected exception", ex);

        return Mono.just(Response.<Void>builder()
                .code("500")
                .info("系统异常")
                .build());
    }
}